package com.ihr360.payroll.controller.reference;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ihr360.commons.exception.Ihr360Exception;
import com.ihr360.commons.vo.ResultInfo;
import com.ihr360.expr.ExprException;
import com.ihr360.expr.core.Expr;
import com.ihr360.expr.function.ExcelFunctionProvider;
import com.ihr360.maven.plugin.ModuleCodeStore;
import com.ihr360.maven.plugin.annotation.FunctionDefinition;
import com.ihr360.maven.plugin.annotation.ModuleDefinition;
import com.ihr360.payroll.config.reference.ReferencePropertyEntity;
import com.ihr360.payroll.config.reference.ReferenceServiceEntity;
import com.ihr360.payroll.dao.ReferenceServiceRepository;
import com.ihr360.payroll.entity.salary.AppliedToWrappers;
import com.ihr360.payroll.model.dto.reference.ReferenceService;
import com.ihr360.payroll.request.IdeographicToCodeRequest;
import com.ihr360.payroll.service.payroll.convertor.ReferenceServiceConvertor;
import com.ihr360.payroll.service.reference.SalaryReferenceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author richey
 */
@Api(value = "薪资引用项相关接口")
@RestController
@RequestMapping("/salary/reference")
@ModuleDefinition(mainModuleCode = ModuleCodeStore.Module.SALARY_CODE_ADMIN, mainModuleName = ModuleCodeStore.Module.SALARY_NAME_ADMIN, hasExtendsAbstractRestController = true,
        subModuleCode = ModuleCodeStore.Module.SalaryAdmin.SALARY_REFERENCE_SETTING_CODE, subModuleName = ModuleCodeStore.Module.SalaryAdmin.SALARY_REFERENCE_SETTING_NAME,
        isPublic = true)
public class SalaryReferenceController {

    @Autowired
    private ReferenceServiceConvertor referenceServiceConvertor;

    @Autowired
    private SalaryReferenceService salaryReferenceService;

    @Autowired
    private ReferenceServiceRepository referenceServiceRepository;

    @ApiOperation(value = "获取引用实体的所有引用属性")
    @GetMapping(value = "/service/properties/{serviceId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "获取引用实体的所有引用属性", functionCode = ModuleCodeStore.Function.VIEW)
    public List<ReferencePropertyEntity> getReferenceSeviceProperties(@PathVariable(name = "serviceId") Long serviceId) {

        return salaryReferenceService.getReferenceServiceProperties(serviceId);
    }

    @ApiOperation(value = "获取所有的引用实体")
    @GetMapping(value = "/service/list", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "获取所有的引用实体", functionCode = ModuleCodeStore.Function.VIEW)
    public List<ReferenceServiceEntity> getAllReferenceService() {
        return salaryReferenceService.getAllReferenceService();
    }

    @ApiOperation(value = "获取指定类型的引用实体")
    @PostMapping(value = "/service/list/appliedto", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "获取指定类型的引用实体", functionCode = ModuleCodeStore.Function.VIEW)
    public List<ReferenceServiceEntity> getAppliedToReferenceService(@RequestBody AppliedToWrappers applies) {
        return salaryReferenceService.getReferenceService(applies);
    }


    @ApiOperation(value = "支持的公式")
    @GetMapping(value = "/salary/excelFunctions", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "支持的公式", functionCode = ModuleCodeStore.Function.VIEW)
    public JSONArray getSupportExcelFunctions() {
        JSONArray result = new JSONArray();
        result.addAll(ExcelFunctionProvider.supportFunctions());
        return result;
    }

    @ApiOperation(value = "处理字符公式得到树结构的Expr")
    @GetMapping(value = "/formular/toExpr/codeFormula", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "处理字符公式得到树结构的Expr", functionCode = ModuleCodeStore.Function.VIEW)
    public Expr getExpr(@RequestParam(name = "formular") String formular) {
        return salaryReferenceService.getIdeographicExprByCodeFormular(formular);
    }


    @ApiOperation(value = "将文字表意公式转换为code表示的公式")
    @GetMapping(value = "/formular/parse/ideographicToCode", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "将文字表意公式转换为code表示的公式", functionCode = ModuleCodeStore.Function.VIEW)
    public JSONObject parsedIdeographicToCodeFormula(@RequestParam(name = "formular") String formular) {
        try {
            return salaryReferenceService.parsedIdeographicToCodeFormula(formular);
        } catch (ExprException e) {
            throw new Ihr360Exception(null, String.format("变量:%s 表达式:%s 解析异常:%s", e.getVariableId(), e.getExpression(), e.getCause().getMessage()));
        }
    }

    @ApiOperation(value = "将文字表意公式转换为code表示的公式,忽略给定变量")
    @PostMapping(value = "/formular/parse/ignore/ideographicToCode", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "将文字表意公式转换为code表示的公式", functionCode = ModuleCodeStore.Function.VIEW)
    public JSONObject parsedIdeographicToCodeFormula(@RequestBody IdeographicToCodeRequest ideographicToCodeRequest) {
        try {
            return salaryReferenceService.parsedIdeographicToCodeFormula(ideographicToCodeRequest.getFormular(),
                    ideographicToCodeRequest.getExtraDatas());
        } catch (ExprException e) {
            throw new Ihr360Exception(null, String.format("变量:%s 表达式:%s 解析异常:%s",
                    e.getVariableId(), e.getExpression(), e.getCause().getMessage()));
        }
    }



    @ApiOperation(value = "将code表示的公式转换为文字表意的公式")
    @GetMapping(value = "/formular/parse/codeToIdeographic", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "将code表示的公式转换为文字表意的公式", functionCode = ModuleCodeStore.Function.VIEW)
    public JSONObject parseCodeToIdeographicFormular(@RequestParam(name = "formular") String formular) {
        return salaryReferenceService.parseCodeToIdeographicFormular(formular);
    }

    @ApiOperation(value = "系统薪资字段文字表意公式循环依赖校验")
    @GetMapping(value = "/ideographicFormular/valid/cirDependency", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "系统薪资字段文字表意公式循环依赖校验", functionCode = ModuleCodeStore.Function.VIEW)
    public JSONObject circularDependencyCheck(@RequestParam(name = "code") String code, @RequestParam(name = "formular") String ideographicFormular) {
        return salaryReferenceService.ideographicCircularDependencyCheck(code, ideographicFormular);
    }

    @ApiOperation(value = "校验薪资表字段文字表意公式是否循环依赖")
    @GetMapping(value = "payrollConfig/ideographicFormular/valid/cirDependency", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "薪资表薪资字段循环依赖校验", functionCode = ModuleCodeStore.Function.VIEW)
    public JSONObject dependencyCheck(@RequestParam(name = "code") String code, @RequestParam(name = "formular") String ideographicFormular, @RequestParam("payrollConfigId") Long payrollConfigId) {
        return salaryReferenceService.payrollConfigDependencyCheck(code, ideographicFormular, payrollConfigId);
    }

    @ApiOperation(value = "保存引用实体")
    @PostMapping(value = "/service/save", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @FunctionDefinition(functionName = "保存引用实体", functionCode = ModuleCodeStore.Function.ADD)
    public ResultInfo saveReferenceService(@RequestBody ReferenceServiceEntity entity) {
        ReferenceService referenceService = referenceServiceConvertor.convertEntityToDto(entity);
        referenceServiceRepository.save(referenceService);
        return new ResultInfo.Builder().message("保存成功！").build();
    }


}
